﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace EmptoolWebApp.Helpers
{
    public class CryptographyHelper
    {
        private static System.Security.Cryptography.MD5 md5Hasher = System.Security.Cryptography.MD5CryptoServiceProvider.Create();

        public static byte[] GetSHA256Hash(byte[] plainTextBytes, byte[] saltBytes)
        {
            System.Security.Cryptography.HashAlgorithm algorithm = new System.Security.Cryptography.SHA256Managed();

            byte[] saltedPlainTextBytes = new byte[plainTextBytes.Length + saltBytes.Length];

            System.Buffer.BlockCopy(plainTextBytes, 0, saltedPlainTextBytes, 0, plainTextBytes.Length);

            System.Buffer.BlockCopy(saltBytes, 0, saltedPlainTextBytes, plainTextBytes.Length, saltBytes.Length);
            
            return algorithm.ComputeHash(saltedPlainTextBytes);
        }

        public static string GetSHA256Hash(string plainText, string salt)
        {
            byte[] plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
            byte[] saltBytes = System.Text.Encoding.UTF8.GetBytes(salt);

            return Convert.ToBase64String(GetSHA256Hash(plainTextBytes, saltBytes));
        }

        public static bool CompareByteArrays(byte[] array1, byte[] array2)
        {
            if (array1.Length != array2.Length)
            {
                return false;
            }

            for (int i = 0; i < array1.Length; i++)
            {
                if (array1[i] != array2[i])
                {
                    return false;
                }
            }

            return true;
        }

        public static byte[] CopyByteArray(byte[] array1, byte[] array2)
        {
            byte[] result = new byte[array1.Length + array2.Length];

            System.Buffer.BlockCopy(array1, 0, result, 0, array1.Length);

            System.Buffer.BlockCopy(array2, 0, result, array1.Length, array2.Length);

            return result;
        }

        public static byte[] CopyByteArray(params byte[][] byteArrayList)
        {
            //byte[] rv = new byte[a1.Length + a2.Length + a3.Length];
            //System.Buffer.BlockCopy(a1, 0, rv, 0, a1.Length);
            //System.Buffer.BlockCopy(a2, 0, rv, a1.Length, a2.Length);
            //System.Buffer.BlockCopy(a3, 0, rv, a1.Length + a2.Length, a3.Length);

            int resultByteLength = 0;
            int offset = 0;

            for (int i = 0; i < byteArrayList.Length; i++)
            {
                resultByteLength = resultByteLength + byteArrayList[i].Length;
            }

            byte[] result = new byte[resultByteLength];

            for (int i = 0; i < byteArrayList.Length; i++)
            {
                System.Buffer.BlockCopy(byteArrayList[i], 0, result, offset, byteArrayList[i].Length);
                offset = offset + byteArrayList[i].Length;
            }

            return result;
        }

        public static string GetMD5Hash(string input)
        {
            // Convert the input string to a byte array and compute the hash.
            byte[] cipherBytes = md5Hasher.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input));

            // Create a new Stringbuilder to collect the bytes and create a string.
            System.Text.StringBuilder stringBuilder = new System.Text.StringBuilder(32);

            // Loop through each byte of the hashed data and format each one as a hexadecimal string.
            foreach (byte b in cipherBytes)
            {
                stringBuilder.Append(b.ToString("x2"));
            }
            
            // Return the hexadecimal string.
            return stringBuilder.ToString();
        }

        // Verify a hash against a string.
        public static bool VerifyMD5Hash(string plainText, string targetCipherText)
        {
            // Hash the input.
            string cipherText = GetMD5Hash(plainText);

            // Create a StringComparer an compare the hashes.
            StringComparer comparer = StringComparer.OrdinalIgnoreCase;

            if (0 == comparer.Compare(cipherText, targetCipherText))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static string UserHash(string input)
        {
            return GetMD5Hash(input);
        }
    }
}